package com.vca.service.service.Impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.vca.common.constants.Constants;
import com.vca.common.exception.VcaException;
import com.vca.common.model.order.StoreOrder;
import com.vca.common.model.order.StoreOrderInfo;
import com.vca.common.model.system.SystemGroupData;
import com.vca.common.model.talk.Talk;
import com.vca.common.model.talk.TalkScheduling;
import com.vca.common.model.user.User;
import com.vca.common.page.CommonPage;
import com.vca.common.request.*;
import com.vca.common.response.AdminHeaderResponse;
import com.vca.common.response.TalkSchedulingAdminByIdResponse;
import com.vca.common.response.TalkSchedulingAdminResponse;
import com.vca.common.utils.DateUtil;
import com.vca.common.utils.PageUtils;
import com.vca.common.utils.VcaUtil;
import com.vca.common.vo.ExcelTalkOrderInfo;
import com.vca.common.vo.ExcelTalkSchedulingById;
import com.vca.common.vo.dateLimitUtilVo;
import com.vca.service.dao.talk.TalkDao;
import com.vca.service.dao.talk.TalkSchedulingDao;
import com.vca.service.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 讲座排期表 服务实现类
 * </p>
 *
 * @author chenBing
 * @since 2022-11-03
 */
@Service
@Slf4j
public class TalkSchedulingServiceImpl extends ServiceImpl<TalkSchedulingDao, TalkScheduling> implements TalkSchedulingService {

    @Autowired
    private TalkSchedulingDao dao;

    @Autowired
    private TalkDao talkDao;

    @Autowired
    private SystemGroupDataService systemGroupDataService;

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private VcaLineUpService vcaLineUpService;

    @Autowired
    private StoreOrderService orderService;

    @Autowired
    private SystemConfigService systemConfigService;

    @Autowired
    private TalkService talkService;

    @Autowired
    private UserService userService;

    @Autowired
    private ExportService exportService;

    @Autowired
    private StoreOrderInfoService orderInfoService;

    /**
     * 讲座排课列表
     *
     * @param request
     * @param pageParamRequest
     * @return
     * @author Li
     * @date 2022/11/15 15:43
     */
    @Override
    public PageInfo getAdminList(SchedulingAdminListRequest request, PageParamRequest pageParamRequest) {
        LambdaQueryWrapper<TalkScheduling> wrapper = new LambdaQueryWrapper();
        wrapper.eq(TalkScheduling::getIsDeleted, 0);
        if (ObjectUtil.isNotEmpty(request.getKeywords())) {
            List<Integer> ids = talkDao.fuzzySearch(request.getKeywords());
            if (ObjectUtil.isEmpty(ids)) {
                List<TalkSchedulingAdminResponse> talkSchedulingAdminResponses = new ArrayList<>();
                return PageUtils.startPage(talkSchedulingAdminResponses, pageParamRequest.getPage(), pageParamRequest.getLimit());
            }
            wrapper.in(TalkScheduling::getTalkId, ids);
        }
        if (ObjectUtil.isNotEmpty(request.getDateLimit())) {
            getRequestTimeWhere(wrapper, request);
        }
        if (ObjectUtil.isNotEmpty(request.getSchedulingStatus())) {
            if (request.getSchedulingStatus().equals(3)) {
                wrapper.eq(TalkScheduling::getIsCancel, 1);
            }
        }
        if (ObjectUtil.isNotEmpty(request.getStatus())) {
            wrapper.eq(TalkScheduling::getStatus, request.getStatus());
        }
        wrapper.orderByDesc(TalkScheduling::getTalkId);
        List<TalkScheduling> schedulings = dao.selectList(wrapper);
        List<TalkSchedulingAdminResponse> adminList = new ArrayList<>();
        if (ObjectUtil.isNotEmpty(schedulings)) {
            LambdaQueryWrapper<Talk> talkWrapper = new LambdaQueryWrapper<>();
            if (ObjectUtil.isNotEmpty(request.getTalkType())) {
                talkWrapper.eq(Talk::getTalkType, request.getTalkType());
            }
            talkWrapper.in(Talk::getId, schedulings.stream().map(TalkScheduling::getTalkId).collect(Collectors.toList()));
            List<Talk> talks = talkDao.selectList(talkWrapper);
            //直播待写
            List languageList = systemGroupDataService.getCourseSchedulingAdminConfig().get("languageList");
            schedulings.forEach(e -> {
                TalkSchedulingAdminResponse response = new TalkSchedulingAdminResponse();
                BeanUtils.copyProperties(e, response);
                if (ObjectUtil.isEmpty(e.getIsCancel())) {
                    response.setSchedulingStatus(DateUtil.getSchedulingStatus(e.getSchedulingDate(), e.getSchedulingStartTime(), e.getSchedulingEndTime()));
                } else {
                    if (e.getIsCancel().equals(1)) {
                        response.setSchedulingStatus(3);
                    } else {
                        response.setSchedulingStatus(DateUtil.getSchedulingStatus(e.getSchedulingDate(), e.getSchedulingStartTime(), e.getSchedulingEndTime()));
                    }
                }
                languageList.forEach(language -> {
                    Map languageMap = JSON.parseObject(JSONObject.toJSONString(language), Map.class);
                    if (languageMap.get("id").equals(e.getCourseLanguageId())) {
                        response.setLanguage(languageMap.get("courseLanguage").toString());
                    }
                });
                talks.forEach(talk -> {
                    if (e.getTalkId().equals(talk.getId())) {
                        response.setName(talk.getName());
                        response.setCoverImage(talk.getCoverImage());
                        response.setTalkType(talk.getTalkType());
                    }
                });
                if (ObjectUtil.isNotEmpty(response.getTalkType())) {
                    adminList.add(response);
                }
            });
        }
        List<TalkSchedulingAdminResponse> responses = adminList;
        if (ObjectUtil.isNotEmpty(request.getSchedulingStatus())) {
            responses = responses.stream().filter(e -> e.getSchedulingStatus().equals(Integer.valueOf(request.getSchedulingStatus()))).collect(Collectors.toList());
        }
        responses.sort(Comparator.comparing(TalkSchedulingAdminResponse::getSchedulingDate));
        return PageUtils.startPage(responses, pageParamRequest.getPage(), pageParamRequest.getLimit());
    }

    @Override
    public ExcelTalkSchedulingById getBookingDetail(String id, PageParamRequest pageParamRequest) {
        /**
         * 查找排期数据
         */
        TalkScheduling talkeScheduling = getById(id);
        if (talkeScheduling == null) {
            throw new VcaException("不存在这个讲座排期");
        }
        Talk talk = talkService.getById(talkeScheduling.getTalkId());
        if (talk == null) {
            throw new VcaException("不存在这个讲座");
        }
        String name = talk.getName(); //名称
        SystemGroupData systemGroupData1 = systemGroupDataService.getById(talkeScheduling.getCourseLanguageId());
        if (systemGroupData1 == null) {
            throw new VcaException("不存在这个课程语言");
        }
        Gson gson = new Gson();
        JsonObject value1 = gson.fromJson(systemGroupData1.getValue(), JsonObject.class);
        String value11 = value1.get("fields").getAsJsonArray().get(0).getAsJsonObject().get("value").getAsString(); //排课语言
        //标题数据
        ExcelTalkSchedulingById excelTalkSchedulingById = new ExcelTalkSchedulingById();
        BeanUtils.copyProperties(talkeScheduling, excelTalkSchedulingById);
        boolean status = exportService.checkExcelStatus(talkeScheduling.getSchedulingDate(), talkeScheduling.getSchedulingStartTime(), talkeScheduling.getSchedulingEndTime());
        excelTalkSchedulingById.setStatus(status ? "已结束" : "未开始");
        excelTalkSchedulingById.setTalkType(talk.getTalkType().equals(1) ? "线下讲座" : "线上讲座");
        excelTalkSchedulingById.setName(talk.getName());
        excelTalkSchedulingById.setCourseLanguage(value11);
        /**
         * 查找核销或待核销的数据
         */
        List<ExcelTalkOrderInfo> list = new ArrayList();
//        excelTalkSchedulingById.setList(list);
        LambdaQueryWrapper<StoreOrderInfo> storeOrderInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        storeOrderInfoLambdaQueryWrapper.eq(StoreOrderInfo::getSchedulingId, id);
        //已核销
        LambdaQueryWrapper<StoreOrder> storeOrderLambdaQueryWrapper = new LambdaQueryWrapper<>();
        storeOrderLambdaQueryWrapper.and(wrapper -> wrapper.in(StoreOrder::getStatus, Arrays.asList(2, 3)).in(StoreOrder::getType, Arrays.asList(0,1,2,3)).or(wrapper1 -> wrapper1.eq(StoreOrder::getPaid, false).eq(StoreOrder::getStatus, 0)));
        storeOrderLambdaQueryWrapper.eq(StoreOrder::getIsDel, false);
        List<StoreOrder> storeOrderList = orderService.list(storeOrderLambdaQueryWrapper);
        //已核销主订单
        List<String> storeOrderNoList = null;
        if(CollectionUtil.isNotEmpty(storeOrderList)) {
            storeOrderNoList = storeOrderList.stream().map(StoreOrder::getOrderId).collect(Collectors.toList());
        }
        //待核销
//        storeOrderInfoLambdaQueryWrapper.eq(StoreOrderInfo::getStatus, 1);
//        storeOrderInfoLambdaQueryWrapper.eq(StoreOrderInfo::getRefundStatus, 0);
        final List<String> finalStoreOrderNoList = storeOrderNoList;
        if(CollectionUtil.isNotEmpty(finalStoreOrderNoList)) {
            storeOrderInfoLambdaQueryWrapper.and(wrapper->wrapper.eq(StoreOrderInfo::getStatus, 1).eq(StoreOrderInfo::getRefundStatus, 0).or().in(CollectionUtil.isNotEmpty(finalStoreOrderNoList), StoreOrderInfo::getOrderNo, finalStoreOrderNoList));
        }else {
            storeOrderInfoLambdaQueryWrapper.eq(StoreOrderInfo::getStatus, 1).eq(StoreOrderInfo::getRefundStatus, 0);
        }
        List<StoreOrderInfo> storeOrderInfos = orderInfoService.list(storeOrderInfoLambdaQueryWrapper);
        if (CollectionUtil.isNotEmpty(storeOrderInfos)) {
            for (int i = 0; i < storeOrderInfos.size(); i++) {
                StoreOrderInfo storeOrderInfo = storeOrderInfos.get(i);
                ExcelTalkOrderInfo excelTalkOrderInfo = new ExcelTalkOrderInfo();
                BeanUtils.copyProperties(storeOrderInfo, excelTalkOrderInfo);
                //购买人
                User buyer = userService.getById(storeOrderInfo.getBuyer());
                if (buyer != null) {
                    excelTalkOrderInfo.setNickname(buyer.getNickname());
                    excelTalkOrderInfo.setPhone(VcaUtil.maskMobile(buyer.getPhone()));
                    excelTalkOrderInfo.setEmail(buyer.getEmail());
                } else {
//                    throw new VcaException("不存在该购买人："+storeOrderInfo.getBuyer());
                }
                //主订单
                StoreOrder storeOrder = orderService.getByOrderId(storeOrderInfo.getOrderNo());
                if (storeOrder != null) {
                    //支付渠道
                    if (storeOrder.getUserType() == 1) {
                        excelTalkOrderInfo.setChannel("后台赠送");
                    } else {
                        excelTalkOrderInfo.setChannel("微信支付");
                    }
                    //主订单uid
                    if(StringUtils.isBlank(excelTalkOrderInfo.getNickname()) && storeOrder.getUid() != null) {
                        User user = userService.getById(storeOrder.getUid());
                        if(user != null) {
                            excelTalkOrderInfo.setNickname(user.getNickname());
                            excelTalkOrderInfo.setPhone(VcaUtil.maskMobile(user.getPhone()));
                            excelTalkOrderInfo.setEmail(user.getEmail());
                        }
                    }
                } else {
//                    throw new VcaException("不存在该主订单："+storeOrderInfo.getOrderNo());
                }
                //核销状态
                if(storeOrder != null) {
                    if(storeOrder.getPaid()) {
                        if (storeOrderInfo.getWriteOffClerkId() == null) {
                            excelTalkOrderInfo.setWriteOffStatus("待核销");
                        } else {
                            excelTalkOrderInfo.setWriteOffStatus("已核销");
                        }
                    }else {
                        excelTalkOrderInfo.setWriteOffStatus("待支付");
                    }
                }
                //核销时间
                if (storeOrderInfo.getWriteOffTime() != null) {
                    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm");
                    excelTalkOrderInfo.setWriteOffTime(simpleDateFormat.format(storeOrderInfo.getWriteOffTime()));
                }
                list.add(excelTalkOrderInfo);
            }
        }
        excelTalkSchedulingById.setPageInfo(CommonPage.restPage(PageUtils.startPage(list, pageParamRequest.getPage(), pageParamRequest.getLimit())));

        return excelTalkSchedulingById;
    }

    /**
     * 讲座排期日历列表
     *
     * @param request
     * @return
     * @author Li
     * @date 2022/11/18 16:32
     */
    @Override
    public List<TalkSchedulingAdminResponse> getCalendarList(SchedulingAdminListRequest request) {
        LambdaQueryWrapper<TalkScheduling> wrapper = new LambdaQueryWrapper();
        if (ObjectUtil.isNotEmpty(request.getKeywords())) {
            wrapper.in(TalkScheduling::getTalkId, talkDao.fuzzySearch(request.getKeywords()));
        }
        if (ObjectUtil.isNotEmpty(request.getStatus())) {
            wrapper.eq(TalkScheduling::getStatus, request.getStatus());
        }
        wrapper.orderByDesc(TalkScheduling::getTalkId);
        List<TalkScheduling> schedulings = dao.selectList(wrapper);
        List<TalkSchedulingAdminResponse> adminList = new ArrayList<>();
        if (ObjectUtil.isNotEmpty(schedulings)) {
            LambdaQueryWrapper<Talk> talkWrapper = new LambdaQueryWrapper<>();
            talkWrapper.in(Talk::getId, schedulings.stream().map(TalkScheduling::getTalkId).collect(Collectors.toList()));
            List<Talk> talks = talkDao.selectList(talkWrapper);
            //直播待写
            String nowDate = DateUtil.nowDate("yyyy-MM-dd HH:mm:ss");
            List languageList = systemGroupDataService.getCourseSchedulingAdminConfig().get("languageList");
            schedulings.forEach(e -> {
                TalkSchedulingAdminResponse response = new TalkSchedulingAdminResponse();
                BeanUtils.copyProperties(e, response);
                response.setSchedulingStatus(DateUtil.getSchedulingStatus(e.getSchedulingDate(), e.getSchedulingStartTime(), e.getSchedulingEndTime()));
                languageList.forEach(language -> {
                    Map languageMap = JSON.parseObject(JSONObject.toJSONString(language), Map.class);
                    if (languageMap.get("id").equals(e.getCourseLanguageId())) {
                        response.setLanguage(languageMap.get("courseLanguage").toString());
                    }
                    talks.forEach(talk -> {
                        if (e.getTalkId().equals(talk.getId())) {
                            response.setName(talk.getName());
                            response.setCoverImage(talk.getCoverImage());
                        }
                    });
                });
                adminList.add(response);
            });
        }
        List<TalkSchedulingAdminResponse> responses = adminList;
        if (ObjectUtil.isNotEmpty(request.getSchedulingStatus())) {
            responses = adminList.stream().filter(e -> e.getSchedulingStatus().equals(Integer.valueOf(request.getSchedulingStatus()))).collect(Collectors.toList());
        }
        return responses;
    }

    /**
     * 添加讲座排期
     *
     * @param request
     * @return
     * @author Li
     * @date 2022/11/18   17:27
     */
    @Override
    public boolean addScheduling(SchedulingAddRequest<TalkSchedulingAddRequest> request) {
        List<TalkScheduling> talkSchedulings = new ArrayList();
        List<Long> talkIds = request.getSchedulingRequests().stream().map(TalkSchedulingAddRequest::getTalkId).collect(Collectors.toList());
        LambdaQueryWrapper<Talk> wrapper = new LambdaQueryWrapper();
        wrapper.eq(Talk::getId, talkIds.get(0));
        Talk talk = talkDao.selectOne(wrapper);
        if (ObjectUtil.isEmpty(talk)) {
            throw new VcaException("该讲座不存在");
        }
        if (request.getSchedulingRequests().get(0).getTalkType().equals(2)) {
            //查询线上讲座排期是否添加过
            List<TalkScheduling> list = this.list(
                    new LambdaQueryWrapper<TalkScheduling>()
                            .eq(TalkScheduling::getTalkId, talkIds.get(0))
                            .eq(TalkScheduling::getIsDeleted, 0));
            if (ObjectUtil.isNotEmpty(list)||list.size()>0){
                throw new VcaException("该线上讲座已添加过排期");
            }
        }
        request.getSchedulingRequests().forEach(e -> {
            TalkScheduling talkScheduling = new TalkScheduling();
            BeanUtils.copyProperties(e, talkScheduling);
            List<String> schedulingTime = VcaUtil.stringToArrayStrRegex(e.getSchedulingTime(), "~");
            talkScheduling.setSchedulingStartTime(schedulingTime.get(0));
            talkScheduling.setSchedulingEndTime(schedulingTime.get(1));
            talkScheduling.setStatus(1);
            talkScheduling.setIsCancel(0);
            talkScheduling.setNumberOfAppointments(0);
            talkScheduling.setNumberOfParticipants(0);
            talkSchedulings.add(talkScheduling);
        });
        boolean sendNotice;
        if (checkSchedulingQuta(talkIds.get(0))) {
            sendNotice = true;
        } else {
            sendNotice = false;
        }
        return transactionTemplate.execute(e -> {
            int a = 0;
            Integer b = 0;
            for (TalkScheduling scheduling : talkSchedulings) {
                dao.insert(scheduling);
                if (checkSchedulingDate(scheduling, talk.getId())) {
                    a++;
                }
            }
            if (a > 0 && sendNotice) {
                vcaLineUpService.noticeByMainId(talkIds.get(0), Constants.ORDER_TYPE_TALK);
            }
            return Boolean.TRUE;
        });
    }

    /**
     * 修改讲座排期
     *
     * @param request
     * @return
     * @author Li
     * @date 2022/11/18   17:27
     */
    @Override
    public boolean updateScheduling(TalkSchedulingAddRequest request) {
        LambdaQueryWrapper<TalkScheduling> wrapper = new LambdaQueryWrapper();
        wrapper.eq(TalkScheduling::getId, request.getId());
        TalkScheduling talkScheduling = dao.selectOne(wrapper);
        if (ObjectUtil.isNotEmpty(request.getQuota())) {
            if (request.getQuota() > talkScheduling.getQuota() && checkSchedulingQuta(request.getId()) && checkSchedulingDate(talkScheduling, request.getTalkId())) {
                vcaLineUpService.noticeByMainId(request.getTalkId(), Constants.ORDER_TYPE_TALK);
            }
            talkScheduling.setQuota(request.getQuota());
        }
        BeanUtils.copyProperties(request, talkScheduling);
        if (ObjectUtil.isEmpty(talkScheduling)) {
            throw new VcaException("当前排课不存在");
        }
        if (ObjectUtil.isNotEmpty(request.getStatus())) {
            talkScheduling.setStatus(request.getStatus());
        }
        if (ObjectUtil.isNotEmpty(request.getCourseLanguageId())) {
            talkScheduling.setCourseLanguageId(request.getCourseLanguageId());
        }
        if (ObjectUtil.isNotEmpty(request.getPrice())) {
            talkScheduling.setPrice(request.getPrice());
        }
        return transactionTemplate.execute(e -> {
            dao.updateById(talkScheduling);
            return Boolean.TRUE;
        });
    }

    /**
     * 跟据讲座id查询排期
     *
     * @param talkId
     * @return
     * @author Li
     * @date 2022/11/21 09:47
     */
    @Override
    public TalkSchedulingAdminByIdResponse getAdminScheduling(Long talkId) {
        LambdaQueryWrapper<TalkScheduling> wrapper = new LambdaQueryWrapper();
        wrapper.eq(TalkScheduling::getId, talkId);
        wrapper.eq(TalkScheduling::getIsDeleted, 0);
        wrapper.eq(TalkScheduling::getStatus, 1);
        wrapper.gt(TalkScheduling::getQuota, 0);
//        wrapper.notIn(TalkScheduling::getSchedulingStatus,0);
        TalkScheduling talkScheduling = dao.selectOne(wrapper);
        if (com.vca.common.utils.DateUtil.getSchedulingStatus(talkScheduling.getSchedulingDate(), talkScheduling.getSchedulingStartTime(), talkScheduling.getSchedulingEndTime()) != 0) {
            throw new VcaException("该讲座不存在");
        }
        Talk talk = talkDao.selectOne(new LambdaQueryWrapper<Talk>().eq(Talk::getId, talkScheduling.getTalkId()));
        if (ObjectUtil.isEmpty(talk)) {
            throw new VcaException("该讲座不存在");
        }

        List languageList = systemGroupDataService.getCourseSchedulingAdminConfig().get("languageList");
        languageList.forEach(language -> {
            Map languageMap = JSON.parseObject(JSONObject.toJSONString(language), Map.class);
            if (languageMap.get("id").equals(talkScheduling.getCourseLanguageId())) {
                talkScheduling.setTalkLanguageName(languageMap.get("courseLanguage").toString());
            }
        });
        TalkSchedulingAdminByIdResponse response = new TalkSchedulingAdminByIdResponse();
        BeanUtils.copyProperties(talkScheduling, response);
        if (ObjectUtil.isEmpty(talkScheduling.getIsCancel())) {
            response.setSchedulingStatus(DateUtil.getSchedulingStatus(talkScheduling.getSchedulingDate(), talkScheduling.getSchedulingStartTime(), talkScheduling.getSchedulingEndTime()));
        } else {
            if (talkScheduling.getIsCancel().equals(1)) {
                response.setSchedulingStatus(3);
            } else {
                response.setSchedulingStatus(DateUtil.getSchedulingStatus(talkScheduling.getSchedulingDate(), talkScheduling.getSchedulingStartTime(), talkScheduling.getSchedulingEndTime()));
            }
        }
        response.setName(talk.getName());
        return response;
    }

    /**
     * 根据讲座排期id删除排期
     *
     * @param schedulingId
     * @return
     * @author Li
     * @date 2022/11/21 14:55
     */
    @Override
    public boolean deleteScheduling(Long schedulingId) {
        LambdaQueryWrapper<TalkScheduling> wrapper = new LambdaQueryWrapper();
        wrapper.eq(TalkScheduling::getId, schedulingId);
        wrapper.eq(TalkScheduling::getIsDeleted, 0);
        TalkScheduling talkScheduling = dao.selectOne(wrapper);
        if (ObjectUtil.isEmpty(talkScheduling)) {
            throw new VcaException("当前排课不存在");
        }
        talkScheduling.setIsDeleted(1);
        talkScheduling.setStatus(0);
        return transactionTemplate.execute(e -> {
            dao.update(talkScheduling, new LambdaUpdateWrapper<TalkScheduling>().eq(TalkScheduling::getId, schedulingId).set(TalkScheduling::getIsDeleted, 1));
            return Boolean.TRUE;
        });
    }

    /**
     * @return
     * @author Li
     * @date 2022/11/24
     */
    @Override
    public List<AdminHeaderResponse> getHeader(String dateLimit, String talkType) {
        //初始化map
        Map<Integer, Integer> status = new HashMap();
        status.put(0, 0);
        status.put(1, 0);
        status.put(2, 0);
        status.put(3, 0);
        List<AdminHeaderResponse> responses = new ArrayList<>();
        LambdaQueryWrapper<TalkScheduling> wrapper = new LambdaQueryWrapper();
        wrapper.eq(TalkScheduling::getIsDeleted, 0);
        if (ObjectUtil.isNotEmpty(dateLimit)) {
            getRequestTimeWhere(wrapper, new SchedulingAdminListRequest().setDateLimit(dateLimit));
        }
        if (ObjectUtil.isNotEmpty(talkType)) {
            List<Talk> talks = talkDao.selectList(new LambdaQueryWrapper<Talk>().eq(Talk::getTalkType, talkType).eq(Talk::getIsDeleted, 0));
            if (ObjectUtil.isEmpty(talks)) {
                responses.add(new AdminHeaderResponse(0, "全部", null, 4));
                responses.add(new AdminHeaderResponse(status.get(0), "已结束", null, 0));
                responses.add(new AdminHeaderResponse(status.get(1), "进行中", null, 1));
                responses.add(new AdminHeaderResponse(status.get(2), "未开始", null, 2));
                return responses;
            }
            wrapper.in(TalkScheduling::getTalkId, talks.stream().map(Talk::getId).collect(Collectors.toList()));
        }
        List<TalkScheduling> talkSchedulings = dao.selectList(wrapper);
        talkSchedulings.forEach(e -> {
            Integer integer = 0;
            if (ObjectUtil.isEmpty(e.getIsCancel())) {
                //动态添加排课状态
                integer = DateUtil.getSchedulingStatus(e.getSchedulingDate(), e.getSchedulingStartTime(), e.getSchedulingEndTime());
            } else {
                if (e.getIsCancel().equals(1)) {
                    integer = 3;
                } else {
                    //动态添加排课状态
                    integer = DateUtil.getSchedulingStatus(e.getSchedulingDate(), e.getSchedulingStartTime(), e.getSchedulingEndTime());
                }
            }

            status.put(integer, status.get(integer) + 1);
        });
        responses.add(new AdminHeaderResponse(talkSchedulings.size(), "全部", null, 4));
        responses.add(new AdminHeaderResponse(status.get(0), "已结束", null, 0));
        responses.add(new AdminHeaderResponse(status.get(1), "进行中", null, 1));
        responses.add(new AdminHeaderResponse(status.get(2), "未开始", null, 2));
        responses.add(new AdminHeaderResponse(status.get(3), "已取消", null, 3));
        return responses;
    }

    /**
     * 上架讲座排期预约状态
     *
     * @param talkSchedulingId 讲座排期id
     * @return
     * @author Li
     * @date 2022/11/18 15:16
     */
    @Override
    public boolean onShell(Long talkSchedulingId) {
        TalkScheduling talkScheduling = checkScheduling(talkSchedulingId);
        talkScheduling.setStatus(1);
        return transactionTemplate.execute(e -> {
            dao.updateById(talkScheduling);
            return Boolean.TRUE;
        });
    }

    /**
     * 下架讲座排期预约状态
     *
     * @param talkSchedulingId 讲座排期id
     * @return
     * @author Li
     * @date 2022/11/18 15:16
     */
    @Override
    public boolean offShell(Long talkSchedulingId) {
        TalkScheduling talkScheduling = checkScheduling(talkSchedulingId);
        talkScheduling.setStatus(0);
        return transactionTemplate.execute(e -> {
            dao.updateById(talkScheduling);
            return Boolean.TRUE;
        });
    }

    /**
     * 跟据讲座id查询排期
     *
     * @param talkId
     * @param pageParamRequest
     * @return
     * @author Li
     * @date 2022/11/21 09:47
     */
    @Override
    public PageInfo<TalkSchedulingAdminByIdResponse> getListByTalk(Long talkId, PageParamRequest pageParamRequest) {
        LambdaQueryWrapper<TalkScheduling> wrapper = new LambdaQueryWrapper();
        wrapper.eq(TalkScheduling::getTalkId, talkId);
        wrapper.eq(TalkScheduling::getIsDeleted, 0);
        wrapper.eq(TalkScheduling::getStatus, 1);
        wrapper.eq(TalkScheduling::getIsCancel, 0);
        List<TalkScheduling> talkSchedulingList = dao.selectList(wrapper);
        List<TalkSchedulingAdminByIdResponse> responses = new ArrayList<>();
        if (ObjectUtil.isEmpty(talkSchedulingList)) {
            return PageUtils.startPage(responses, pageParamRequest.getPage(), pageParamRequest.getLimit());
        }
        List languageList = systemGroupDataService.getCourseSchedulingAdminConfig().get("languageList");
        talkSchedulingList.forEach(e -> {
            languageList.forEach(language -> {
                Map languageMap = JSON.parseObject(JSONObject.toJSONString(language), Map.class);
                if (languageMap.get("id").equals(e.getCourseLanguageId())) {
                    e.setTalkLanguageName(languageMap.get("courseLanguage").toString());
                }
            });
        });
        List<TalkSchedulingAdminByIdResponse> talkSchedulingVos = new ArrayList<TalkSchedulingAdminByIdResponse>();
        talkSchedulingList.forEach(e -> {
            TalkSchedulingAdminByIdResponse talkSchedulingVo = new TalkSchedulingAdminByIdResponse();
            BeanUtils.copyProperties(e, talkSchedulingVo);
            talkSchedulingVo.setPrice(e.getPrice());
            talkSchedulingVo.setSchedulingStatus(DateUtil.getSchedulingStatus(e.getSchedulingDate(), e.getSchedulingStartTime(), e.getSchedulingEndTime()));
            //过滤出未开始的
            if (talkSchedulingVo.getSchedulingStatus() == 2) {
                talkSchedulingVos.add(talkSchedulingVo);
            }
        });
        responses = talkSchedulingVos.stream().sorted(Comparator.comparing(TalkSchedulingAdminByIdResponse::getQuota).reversed()).collect(Collectors.toList());
        responses.sort(Comparator.comparing(TalkSchedulingAdminByIdResponse::getSchedulingDate));
        return PageUtils.startPage(responses, pageParamRequest.getPage(), pageParamRequest.getLimit());
    }

    /**
     * @param request
     * @return java.lang.Boolean
     * @description 线上讲座绑定微吼直播
     * @author Li
     * @date 2022/12/27 14:52
     */
    @Override
    public Boolean TalkBindingVhall(TalkBindingVhallRequest request) {
        TalkScheduling talkScheduling = this.checkScheduling(request.getTalkSchedulingId());
        talkScheduling.setLiveId(Long.parseLong(request.getWebinarId()));
        talkScheduling.setLiveStatus(Integer.valueOf(request.getStatus()));
        return transactionTemplate.execute(e -> {
            dao.updateById(talkScheduling);
            return Boolean.TRUE;
        });
    }

    /**
     * @param request
     * @return boolean
     * @description 取消讲座排期
     * @methodName cancel
     * @author Li
     * @date 2022/12/28 16:15
     */
    @Override
    public boolean cancel(SchedulingCancelRequest request) {
        TalkScheduling talkScheduling = checkScheduling(request.getSchedulingId());
        talkScheduling.setIsCancel(1);
        talkScheduling.setCancellationReasons(request.getReason());
        return transactionTemplate.execute(e -> {
            orderService.cancelActivity(request.getSchedulingId().intValue(), 2);
            dao.updateById(talkScheduling);
            return Boolean.TRUE;
        });
    }

    /**
     * @Description:判断讲座排期是否还有空余席位
     * @author:chenbing
     * @date 2023/9/18 16:57
     */
    @Override
    public boolean checkSchedulingQuta(Long mainId) {
        List<TalkScheduling> schedulings = list(new LambdaQueryWrapper<TalkScheduling>()
                .eq(TalkScheduling::getTalkId, mainId)
                .eq(TalkScheduling::getIsDeleted, false)
                .eq(TalkScheduling::getIsCancel,0)
                .gt(TalkScheduling::getSchedulingDate, DateUtil.dateToStr(new Date(), Constants.DATE_FORMAT_DATE))
                .gt(TalkScheduling::getSchedulingEndTime, DateUtil.dateToStr(new Date(), "HH:mm")));
        if (schedulings.size() <= 0) {
            return true;
        }
        int quota = schedulings.stream().mapToInt(TalkScheduling::getQuota).sum();
        if (quota <= 0) {
            return true;
        }
        return false;
    }

    /**
     * @Description:判断当前排期似乎否已经过了停止预约的时间
     * @author:chenbing
     * @date 2023/9/19 13:44
     */
    @Override
    public boolean checkSchedulingDate(TalkScheduling talkScheduling, Long mainId) {
        if (talkScheduling == null) {
            return false;
        }
        Talk talk = talkDao.selectById(mainId);
        //TODO：获取课程提前停止预约时间
        Integer courseEndOrderTimeHour = 0;
        if (talk.getTalkType() == 1) {
            courseEndOrderTimeHour = Integer.valueOf(systemConfigService.getValueByKey(Constants.TALK_END_ORDER_TIME));
        }
        if (talk.getTalkType() == 2) {
            courseEndOrderTimeHour = Integer.valueOf(systemConfigService.getValueByKey(Constants.ONLINE_TALK_END_ORDER_TIME));
        }
        Date schedulingDate = DateUtil.strToDate(talkScheduling.getSchedulingDate() + " " + talkScheduling.getSchedulingStartTime() + ":00", "yyyy-MM-dd HH:mm:ss");
        DateTime offset = cn.hutool.core.date.DateUtil.offset(schedulingDate, DateField.HOUR, -courseEndOrderTimeHour);
        long between = cn.hutool.core.date.DateUtil.between(offset, cn.hutool.core.date.DateUtil.date(), DateUnit.SECOND, false);
        if (between >= 0) {
            return false;
        }
        return true;
    }

    private TalkScheduling checkScheduling(Long talkSchedulingId) {
        LambdaQueryWrapper<TalkScheduling> wrapper = new LambdaQueryWrapper();
        wrapper.eq(TalkScheduling::getId, talkSchedulingId);
        wrapper.eq(TalkScheduling::getIsDeleted, 0);
        TalkScheduling talkScheduling = dao.selectOne(wrapper);
        if (ObjectUtil.isEmpty(talkScheduling)) {
            throw new VcaException("当前排期不存在");
        }
        return talkScheduling;
    }

    /**
     * 获取request的where条件
     *
     * @param queryWrapper QueryWrapper<StoreOrder> 表达式
     * @param request      StoreOrderSearchRequest 请求参数
     */
    private void getRequestTimeWhere(LambdaQueryWrapper<TalkScheduling> queryWrapper, SchedulingAdminListRequest request) {
        if (StringUtils.isNotBlank(request.getDateLimit())) {
            dateLimitUtilVo dateLimitUtilVo = DateUtil.getDateLimit(request.getDateLimit());
            queryWrapper.between(TalkScheduling::getSchedulingDate, dateLimitUtilVo.getStartTime().substring(0, 10), dateLimitUtilVo.getEndTime().substring(0, 10));
        }
    }

}
